/**
 * 事件系统，初始化时需要挂载到表单上
 */
import { getOpt } from './opts'
import { getWorker } from './tasks'

const isString = (obj) => {
  return Object.prototype.toString.call(obj) === '[object String]'
}

export default class EventManager {
  form = null
  rules = {} // 事件定义

  constructor(form) {
    this.form = form
    // this.rules = rules

    this.init()
  }

  init() {
    const rules = this.rules = {}
    const controls = this.form.options.data
    // debugger

    controls.forEach(item => {
      if (item.events) {
        const events = isString(item.events) ? JSON.parse(item.events) : item.events
        events.forEach(evt => {
          const itemRules = rules[item.name] || (rules[item.name] = [])
          itemRules.push(evt)
        })
      }
      if (item.dataLinkage) {
        const dataLinkage = isString(item.dataLinkage) ? JSON.parse(item.dataLinkage) : item.dataLinkage
        dataLinkage.forEach(evt => {
          const itemRules = rules[item.name] || (rules[item.name] = [])
          itemRules.push(evt)
        })
      }
    })
  }

  // 事件发生时检查是否需要处理
  checkEvent(type, e) {
    const target = $(e.target)
    const name = target.data('name')
    const rules = this.rules[name]
    if (rules && rules.length > 0) {
      rules.forEach(rule => {
        if (rule.triggerType === type) {
          this.processEvent(rule, name)
        }
      })
    }
  }

  processEvent(rule, currentName) {
    const { relationType, groups, tasks, refAction } = rule
    const conditions = {
      relationType,
      conditions: groups
    }

    if(refAction){  //数据联动直接执行相关操作，把引用数据的值赋值给相关字段
      this.doTasks(tasks, currentName)
    }else if (this.validate(conditions)) {  //校验通过后进行相关操作
      this.doTasks(tasks)
    }
  }

  getValue(name) {
    const values = this.form.getValue()
    return values && values[name]
  }

  // 条件是否满足规定
  validate(rule) {
    const { relationType, conditions, name, value, compareType } = rule

    if (relationType) { // 集合规则
      if(relationType === "release"){
        return true
      }else{
        const isOr = relationType === 'or'
        return isOr ?
          conditions.some(item => this.validate(item)) :
          conditions.every(item => this.validate(item))
      }
    } else if (name && compareType) {
      const current = this.getValue(name)
      return getOpt(compareType).caculate(current, value)
    } else {
      console.warn('error check conditions: ', rule)
      return false
    }
  }

  // 执行任务
  doTasks(tasks, currentName) {
    tasks.forEach(({ name, propName, propValue }) => {
      const Worker = getWorker(propName, name)
      if (Worker) {
        const worker = new Worker(this.form, name, propValue)
        worker.run(currentName, propValue)
      } else {
        console.warn('no proper worker ', propName)
      }
      // console.log('tasks', task)
    })
  }
}
